from django.utils import timezone
from django.db import transaction
from decimal import Decimal
from datetime import datetime, timedelta
from .models import DataSyncTask, DataSyncLog, FundInfo, FundNavDetail
from products.models import Product, ProductCategory
import logging
import json

logger = logging.getLogger(__name__)

class DataSyncService:
    """数据同步服务"""
    
    def __init__(self):
        self.logger = logging.getLogger(__name__)
    
    def execute_sync_task(self, task_id):
        """
        执行同步任务
        task_id: 同步任务ID
        """
        task = None
        log = None
        try:
            # 定义开始时间
            start_time = timezone.now()
            
            # 获取任务
            task = DataSyncTask.objects.get(id=task_id)
            
            # 更新任务状态
            task.status = 'running'
            task.last_sync_time = start_time
            task.save()
            
            # 创建同步日志
            log = DataSyncLog.objects.create(
                task=task,
                start_time=start_time,
                status='running'
            )
            
            try:
                # 根据同步类型执行不同的同步逻辑
                if task.sync_type == 'fund_data':
                    result = self._sync_fund_data(task)
                elif task.sync_type == 'fund_net_value':
                    result = self._sync_fund_net_value(task)
                elif task.sync_type == 'market_data':
                    result = self._sync_market_data(task)
                else:
                    result = self._sync_sample_data(task)
                
                # 更新任务状态为成功
                task.status = 'completed'
                task.save()
                
                # 更新日志
                log.status = 'success'
                log.records_processed = result.get('success', 0)
                log.records_failed = result.get('error', 0)
                log.end_time = timezone.now()
                log.save()
                
                # 添加status字段到返回结果
                result['status'] = 'success'
                
                self.logger.info(f"任务 {task_id} 执行成功: {result}")
                return result
                
            except Exception as e:
                error_msg = f"同步任务执行失败: {str(e)}"
                self.logger.error(error_msg)
                
                # 更新任务状态为失败
                if task is not None:
                    task.status = 'failed'
                    task.save()
                
                # 更新日志
                if log is not None:
                    log.status = 'failed'
                    log.error_message = str(e)
                    log.end_time = timezone.now()
                    log.save()
                
                return {'success': 0, 'error': 1, 'message': error_msg, 'status': 'failed'}
                
        except DataSyncTask.DoesNotExist:
            error_msg = f"同步任务 {task_id} 不存在"
            self.logger.error(error_msg)
            return {'success': 0, 'error': 1, 'message': error_msg, 'status': 'failed'}
        
        except Exception as e:
            error_msg = f"任务执行失败: {str(e)}"
            self.logger.error(error_msg)
            return {'success': 0, 'error': 1, 'message': error_msg, 'status': 'failed'}
    
    def _sync_fund_data(self, task):
        """
        同步基金数据
        """
        try:
            # 获取同步参数
            sync_params = task.sync_params or {}
            fund_codes = sync_params.get('fund_codes', [])
            
            # 创建示例基金数据
            sample_funds = self._get_sample_fund_data()
            
            # 如果指定了基金代码，只同步指定的基金
            if fund_codes:
                sample_funds = [f for f in sample_funds if f['fund_code'] in fund_codes]
            
            success_count = 0
            error_count = 0
            
            with transaction.atomic():
                # 获取或创建基金产品分类
                fund_category, _ = ProductCategory.objects.get_or_create(
                    name='基金',
                    defaults={'description': '基金产品'}
                )
                
                for fund_data in sample_funds:
                    try:
                        # 创建或更新产品
                        product, created = Product.objects.get_or_create(
                            code=fund_data['fund_code'],
                            defaults={
                                'name': fund_data['fund_name'],
                                'category': fund_category,
                                'product_type': 'fund',
                                'risk_level': fund_data.get('risk_level', 3),
                                'manager': fund_data.get('manager_name', '未知'),
                                'company': fund_data.get('fund_company', '未知'),
                                'establishment_date': fund_data.get('establish_date', timezone.now().date()),
                                'management_fee': fund_data.get('management_fee', Decimal('0.015')),
                                'custody_fee': fund_data.get('custodian_fee', Decimal('0.0025')),
                                'subscription_fee': fund_data.get('subscription_fee', Decimal('0.015')),
                                'redemption_fee': fund_data.get('redemption_fee', Decimal('0.005')),
                                'min_investment': Decimal('1000'),
                                'status': 'active',
                            }
                        )
                        
                        if not created:
                            # 更新产品信息
                            product.name = fund_data['fund_name']
                            product.manager = fund_data.get('manager_name', product.manager)
                            product.company = fund_data.get('fund_company', product.company)
                            product.establishment_date = fund_data.get('establish_date', product.establishment_date)
                            product.management_fee = fund_data.get('management_fee', product.management_fee)
                            product.custody_fee = fund_data.get('custodian_fee', product.custody_fee)
                            product.subscription_fee = fund_data.get('subscription_fee', product.subscription_fee)
                            product.redemption_fee = fund_data.get('redemption_fee', product.redemption_fee)
                            product.save()
                        
                        # 创建或更新基金数据
                        fund_obj, fund_created = FundInfo.objects.get_or_create(
                            fund_code=fund_data['fund_code'],
                            defaults={
                                'product': product,
                                'fund_name': fund_data['fund_name'],
                                'fund_type': fund_data['fund_type'],
                                'fund_company': fund_data['fund_company'],
                                'manager_name': fund_data.get('manager_name', ''),
                                'establish_date': fund_data.get('establish_date'),
                                'fund_size': fund_data.get('fund_size'),
                                'management_fee': fund_data.get('management_fee'),
                                'custodian_fee': fund_data.get('custodian_fee'),
                                'subscription_fee': fund_data.get('subscription_fee'),
                                'redemption_fee': fund_data.get('redemption_fee'),
                                'data_date': timezone.now().date(),
                            }
                        )
                        
                        if not fund_created:
                            # 更新基金数据
                            fund_obj.fund_name = fund_data['fund_name']
                            fund_obj.fund_type = fund_data['fund_type']
                            fund_obj.fund_company = fund_data['fund_company']
                            fund_obj.manager_name = fund_data.get('manager_name', fund_obj.manager_name)
                            fund_obj.save()
                        
                        success_count += 1
                        self.logger.info(f"成功同步基金 {fund_data['fund_code']}")
                        
                    except Exception as e:
                        error_count += 1
                        self.logger.error(f"同步基金 {fund_data['fund_code']} 失败: {e}")
                        continue
            
            return {
                'success': success_count,
                'error': error_count,
                'message': f'基金数据同步完成: 成功 {success_count}, 失败 {error_count}'
            }
            
        except Exception as e:
            self.logger.error(f"基金数据同步失败: {e}")
            return {'success': 0, 'error': 1, 'message': str(e)}
    
    def _sync_fund_net_value(self, task):
        """
        同步基金净值数据
        """
        try:
            # 获取同步参数
            sync_params = task.sync_params or {}
            fund_code = sync_params.get('fund_code')
            days = sync_params.get('days', 30)
            
            if not fund_code:
                return {'success': 0, 'error': 1, 'message': '未指定基金代码'}
            
            # 获取基金对象
            try:
                fund_data = FundInfo.objects.get(fund_code=fund_code)
            except FundInfo.DoesNotExist:
                return {'success': 0, 'error': 1, 'message': f'基金 {fund_code} 不存在'}
            
            # 生成示例净值数据
            net_values = self._generate_sample_net_values(fund_code, days)
            
            success_count = 0
            for net_value_data in net_values:
                try:
                    FundNavDetail.objects.update_or_create(
                        fund_code=fund_data.fund_code,
                        nav_date=net_value_data['nav_date'],
                        defaults={
                            'unit_nav': net_value_data['unit_nav'],
                            'cumulative_nav': net_value_data['accumulated_nav'],
                            'daily_return': net_value_data.get('daily_return'),
                        }
                    )
                    success_count += 1
                except Exception as e:
                    self.logger.error(f"保存净值数据失败: {e}")
                    continue
            
            return {
                'success': success_count,
                'error': 0,
                'message': f'基金 {fund_code} 净值同步完成: {success_count} 条'
            }
            
        except Exception as e:
            self.logger.error(f"净值数据同步失败: {e}")
            return {'success': 0, 'error': 1, 'message': str(e)}
    
    def _sync_market_data(self, task):
        """
        同步市场数据
        """
        # 这里可以实现市场数据同步逻辑
        return {
            'success': 1,
            'error': 0,
            'message': '市场数据同步完成（示例）'
        }
    
    def _sync_sample_data(self, task):
        """
        同步示例数据
        """
        return {
            'success': 1,
            'error': 0,
            'message': '示例数据同步完成'
        }
    
    def _get_sample_fund_data(self):
        """
        获取示例基金数据
        """
        return [
            {
                'fund_code': '000001',
                'fund_name': '华夏成长混合',
                'fund_type': 'hybrid',
                'fund_company': '华夏基金管理有限公司',
                'manager_name': '张三',
                'establish_date': datetime(2020, 1, 1).date(),
                'fund_size': Decimal('1000000'),
                'management_fee': Decimal('0.015'),
                'custodian_fee': Decimal('0.0025'),
                'subscription_fee': Decimal('0.015'),
                'redemption_fee': Decimal('0.005'),
                'risk_level': 3,
            },
            {
                'fund_code': '000002',
                'fund_name': '易方达价值精选混合',
                'fund_type': 'hybrid',
                'fund_company': '易方达基金管理有限公司',
                'manager_name': '李四',
                'establish_date': datetime(2019, 6, 1).date(),
                'fund_size': Decimal('800000'),
                'management_fee': Decimal('0.015'),
                'custodian_fee': Decimal('0.0025'),
                'subscription_fee': Decimal('0.015'),
                'redemption_fee': Decimal('0.005'),
                'risk_level': 4,
            },
            {
                'fund_code': '000003',
                'fund_name': '南方稳健成长混合',
                'fund_type': 'hybrid',
                'fund_company': '南方基金管理股份有限公司',
                'manager_name': '王五',
                'establish_date': datetime(2018, 3, 15).date(),
                'fund_size': Decimal('1200000'),
                'management_fee': Decimal('0.015'),
                'custodian_fee': Decimal('0.0025'),
                'subscription_fee': Decimal('0.015'),
                'redemption_fee': Decimal('0.005'),
                'risk_level': 2,
            },
        ]
    
    def _generate_sample_net_values(self, fund_code, days):
        """
        生成示例净值数据
        """
        net_values = []
        base_nav = Decimal('1.0000')
        accumulated_nav = Decimal('1.0000')
        
        for i in range(days):
            nav_date = (datetime.now() - timedelta(days=days-i-1)).date()
            
            # 模拟净值波动
            import random
            daily_change = Decimal(str(random.uniform(-0.03, 0.03)))  # -3% 到 3% 的日波动
            
            if i == 0:
                unit_nav = base_nav
            else:
                unit_nav = net_values[-1]['unit_nav'] * (1 + daily_change)
                unit_nav = round(unit_nav, 4)
            
            accumulated_nav = accumulated_nav * (1 + daily_change)
            accumulated_nav = round(accumulated_nav, 4)
            
            daily_return = daily_change * 100  # 转换为百分比
            
            net_values.append({
                'nav_date': nav_date,
                'unit_nav': unit_nav,
                'accumulated_nav': accumulated_nav,
                'daily_return': round(daily_return, 2),
            })
        
        return net_values


# 创建全局实例
sync_service = DataSyncService()